package com.topisv.tms.service.pickCar;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.EdiOrderItem;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.pickCar.PickCar;
import com.topisv.tms.entity.pickCar.PickCarStock;
import com.topisv.tms.entity.pickCar.PickCarStockSku;
import com.topisv.tms.entity.work.WorkLog;
import com.topisv.tms.entity.work.WorkOrder;
import com.topisv.tms.entity.work.WorkTask;
import com.topisv.tms.repository.AreaGroupDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.UserDao;
import com.topisv.tms.repository.pickCar.PickCarDao;
import com.topisv.tms.repository.pickCar.PickCarStockDao;
import com.topisv.tms.repository.pickCar.PickCarStockSkuDao;
import com.topisv.tms.repository.work.WorkLogDao;
import com.topisv.tms.repository.work.WorkTaskDao;
import com.topisv.tms.service.work.WorkOrderService;

/**
 * 拣货车_service
 * 
 * @author ch
 * 
 */
@Component
@Transactional(readOnly = true)
public class PickCarService {
	private Logger log= LoggerFactory.getLogger(PickCarService.class);
	@Autowired
	private JdbcTemplate jdbcTemplate;
	@Autowired
	private PickCarDao pickCarDao;
	@Autowired
	private PickCarStockDao pickCarStockDao;
	@Autowired
	private CustomersDao customersDao;
	@Autowired
	private AreaGroupDao areaGroupDao;
	@Autowired
	private WorkTaskDao workTaskDao;
	@Autowired
	private WorkOrderService workOrderService;
	@Autowired
	private PickCarStockSkuDao pickCarStockSkuDao;
	@Autowired
	private UserDao userDao;
	@Autowired
	private WorkLogDao workLogDao;
	/**
	 * 查询拣货车
	 * @param customerCode 商家编码
	 * @param warehouseCode 仓库编码
	 * @return
	 */
	public List<PickCar> loadCar(String customerCode, String warehouseCode,String status) {
		return this.pickCarDao.loadCar(customerCode,warehouseCode,status);
	}

	/**
	 * 查找拣货车
	 * @param param
	 * @return
	 */
	public List<PickCar> loadPickCarByParam(Map<String, Object> param) {
		Specification<PickCar> spec = getWhereClause(param);
		List<PickCar> pickCarList= this.pickCarDao.findAll(spec);
		for (PickCar pickCar : pickCarList) {
			pickCar.setCustomer(this.customersDao.findByCustomerCode(pickCar.getCustomerCode()));
			pickCar.setWarehouse(this.areaGroupDao.findByGroupCode(pickCar.getWarehouseCode()));
		}
		return pickCarList;
	}
	
	/**
	 * 查询条件封装
	 * @param param
	 * @return
	 */
	private Specification<PickCar> getWhereClause(final Map<String, Object> param) {
		
		return new Specification<PickCar>(){
			
		    @Override
		    public Predicate toPredicate(Root<PickCar> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
		      Predicate pre = cb.conjunction();
		      
		      String customerCode=(String) param.get("customerCode");
		      if(StringUtils.isNotEmpty(customerCode)){
					pre.getExpressions().add(cb.equal(r.get("customerCode"),customerCode));
			  }

		      String warehouseCode=(String) param.get("warehouseCode");
		      if(StringUtils.isNotEmpty(warehouseCode)){
		    	  pre.getExpressions().add(cb.equal(r.get("warehouseCode"),warehouseCode));
		      }
		      
		      String status=(String) param.get("status");
		      if(StringUtils.isNotEmpty(status)){
		    	  pre.getExpressions().add(cb.equal(r.get("status"),status));
		      }
		      
		      return pre;
		    }
		  };
       }

	/**
	 * 创建拣货车
	 * @param pickCar 拣货车
	 */
	@Transactional(readOnly = false, rollbackFor=Exception.class)
	public void save(PickCar pickCar) throws Exception {
		try {
			
			Integer stockNum=pickCar.getStockNum();
			pickCar.setStatus("free");

			List<PickCarStock> stockList=new ArrayList<PickCarStock>();
			for (int i = 1; i <=stockNum; i++) {
				PickCarStock stock=new PickCarStock();
				stock.setCar(pickCar);
				stock.setStatus("free");
				stock.setStockCode(i+"");
				stock.setStockName("第"+i+"号");
				stockList.add(stock);
			}
			this.pickCarStockDao.save(stockList);
			
			this.pickCarDao.save(pickCar);
		
		} catch (Exception e) {
			throw new Exception(e);
		}
		
	}

	/**
	 * 删除拣货车
	 * @param pickCarId 拣货车ID
	 * @throws Exception 
	 */
	@Transactional(readOnly = false, rollbackFor=Exception.class)
	public void delete(Long pickCarId) throws Exception {
		try {
			PickCar pickCar=this.pickCarDao.findOne(pickCarId);
			List<PickCarStock> stockList=this.pickCarStockDao.loadStockByCarId(pickCarId);
			this.pickCarStockDao.delete(stockList);
			this.pickCarDao.delete(pickCar);
		} catch (Exception e) {
			throw new Exception(e);
		}
		
	}

	/**
	 * 查询拣货车
	 * @param pickCarId 拣货车Id
	 * @return
	 */
	public PickCar loadPickCarById(Long pickCarId) {
		return this.pickCarDao.findOne(pickCarId);
	}

	/**
	 * 商品上架
	 * @param carId 拣选车ID
	 * @param sku  sku 
	 * @param taskId 任务ID
	 * @return busy:拣选车使用中   hasfinished:任务已经完成    error:异常   success:上架验证通过
	 * @throws Exception 
	 */
	@Transactional(readOnly = false, rollbackFor=Exception.class)
	public Map<String,String> setGoods(Long carId, String sku, Long taskId) throws Exception {
		
			Map<String,String> result=new HashMap<String, String>();
			WorkTask task=this.workTaskDao.findOne(taskId);
			PickCar car=this.pickCarDao.findOne(carId);
			if(null == car){
				result.put("msg", "carnoexist");
				return result;
			}
			List<PickCarStock> stockList=null;
			String taskCode=task.getTaskCode();
			
			//订单信息
			Map<String, Object> param=new HashMap<String, Object>();
		    param.put("taskCode",taskCode);
			stockList=this.pickCarStockDao.loadStockByCarId(carId);
			
			//确定放置架位、判断是否商品全部入位====================================================================
			if(car.getTaskCode() ==null) {
				log.error(" car("+car.getCarCode()+","+car.getCarName()+") havn't bind to any task. ("+taskCode+")" );
			}  else if( car.getTaskCode().equals(taskCode)){
				
				//任务已经完成
				List<PickCarStockSku> allStockSkuList=this.pickCarStockSkuDao.loadUnSet(car.getId(),taskCode);
				if(allStockSkuList.size()==0){
					result.put("msg", "hasfinished");
					return result;
				}
				
				//确定放置架位
				PickCarStock sel_stock=null;
				boolean flag=false;
				for (PickCarStock _stock : stockList) {
					List<PickCarStockSku> _stockSkuList=this.pickCarStockSkuDao.loadByStockId(_stock.getId());
					for (PickCarStockSku _stockSku : _stockSkuList) {
						if(_stockSku.getSku().toUpperCase().equals(sku.toUpperCase()) && _stockSku.getUpStatus().equals("0")){
							log.info("set stock ("+_stockSku.getId()+") code="+_stock.getStockCode()+",  sku :" + sku);
							_stockSku.setUpStatus("1");
							pickCarStockSkuDao.save(_stockSku);
							flag=true;
							break;
						}
					}
					if(flag==true){
						sel_stock=_stock;
						break;
					}
				}
				
				//验证上架通过
				if(sel_stock!=null){
					result.put("msg", "success");
					log.info("put stock = " + sel_stock.getStockCode());
					result.put("stockCode",sel_stock.getStockCode());
					//验证商品是否全部入位
					List<PickCarStockSku> unSetList=this.pickCarStockSkuDao.loadUnSet(task.getPickcarId(),taskCode);
					log.info("unset num = " + unSetList.size());
					if(unSetList!=null && unSetList.size()==0){
						result.put("isFinished", "finished"); //全部入位
						
						//如果是推车拣选，需要清空推车数据
						if("car".equals(task.getPickModel())){
							Long _carId=task.getPickcarId();
							PickCar _car=this.pickCarDao.findOne(carId);
							_car.setStatus("free");
							_car.setBatchCode(null);
							_car.setTaskCode(null);
							this.pickCarDao.save(_car);
							
							List<PickCarStock> _stockList=this.pickCarStockDao.loadStockByCarId(carId);
							for (PickCarStock stock : _stockList) {
								stock.setGoodsInfo(null);
								stock.setGoodsNum(null);
								stock.setOrderno(null);
								stock.setBatchCode(null);
								stock.setTaskCode(null);
								stock.setStatus("free");
							}
							
							this.pickCarStockDao.save(_stockList);
							
							List<PickCarStockSku> _stockSkuList=this.pickCarStockSkuDao.loadByCarId(_carId);
							this.pickCarStockSkuDao.delete(_stockSkuList);
						}
						
					}else{
						result.put("isFinished", "notfinished"); //没有全部入位
					}
					return result;
				} else {
					log.error("unfound car stock " );
				}
				
			} else {
				log.error(" car("+car.getCarCode()+","+car.getCarName()+") binded another task ("+taskCode+")" );
			}
			
			result.put("msg", "error");
			return result;

	}
	
	public PickCar loadCarByCode(String carCode) {
		return this.pickCarDao.loadCarByCode(carCode);
	}

	/**
	 * 任务绑定推车
	 * @param carCode 车编码
	 * @param taskCode 任务编码
	 * @return busy：推车被占用  success:推车绑定任务成功
	 * @throws Exception 
	 */
	@Transactional(readOnly = false, rollbackFor=Exception.class)
	public String bindCar(String carCode, String taskCode,String jobuuid) throws Exception {
		try {
				PickCar car=this.loadCarByCode(carCode);
				if(null == car){
					return "noexist";
				}
				User user = findUserByjobuuid(jobuuid);
				List<PickCarStock> stockList=null;
				List<PickCarStockSku> stockSkuList=null;
				
				WorkTask task=this.workTaskDao.loadTaskByTaskCode(taskCode);
				String batchCode=task.getBatchCode();
				
				if ("1".equals(task.getFastFlag())) {
	                return "fast"; //已经被快捷领取
	            }
				  
				//拣选车被其它任务占用
				if(car.getStatus().equals("busy")){
					return "busy"; 
				}
				
				//continue任务
				if(task.getStatus().equals("11") ){
					if(!carCode.equals(task.getPickcarCode())){
						return "unfixed";  //推车编码和任务不匹配
					}else{
						return "continue"; //继续任务
					}
				}
				

				
				//车位不够
				if(car.getStockNum()<task.getOrderQty()){
					return "less"; 
				}
				
				//订单信息
				Map<String, Object> param=new HashMap<String, Object>();
			    param.put("taskCode",taskCode);
			    List<WorkOrder> orderList=this.workOrderService.loadOrder(param);
					
			    //绑定拣选车
				car.setStatus("busy");
				car.setBatchCode(batchCode);
				car.setTaskCode(taskCode);
				this.pickCarDao.save(car);
				
				stockList=new ArrayList<PickCarStock>();
				stockSkuList=new ArrayList<PickCarStockSku>();
				
				//绑定拣选车位、写入拣选车明细信息
				for (WorkOrder workOrder : orderList) {
					
					int rankno=workOrder.getRankno();
					PickCarStock stock=this.pickCarStockDao.loadStockByCondition(car.getId(),rankno+"");
					
					int goodsNum=0; String goodsInfo="";
		            List<EdiOrderItem> itemList=workOrder.getOrder().getOrderItems();
					for (EdiOrderItem orderItem : itemList) {
						int _qty=orderItem.getQty();
						String _sku=orderItem.getSku();
						goodsNum+=_qty;
		                goodsInfo+=_sku+"_"+_qty+";";
		                for(int i=0;i<_qty;i++){
		                	PickCarStockSku stockSku=new PickCarStockSku();
		                	stockSku.setCar(car);
		                	stockSku.setStock(stock);
		                	stockSku.setSku(_sku);
		                	stockSku.setNum(1);
		                	stockSku.setBatchCode(batchCode);
		                	stockSku.setTaskCode(taskCode);
		                	stockSku.setUpStatus("0");
		                	stockSkuList.add(stockSku);
		                }
					}
					
					stock.setStatus("busy");
					stock.setGoodsInfo(goodsInfo);
					stock.setGoodsNum(goodsNum);
					stock.setBatchCode(batchCode);
					stock.setTaskCode(taskCode);
					stock.setOrderno(workOrder.getOrder().getOrdeno());
					stockList.add(stock);
				}
				
				this.pickCarStockDao.save(stockList);
				this.pickCarStockSkuDao.save(stockSkuList);
				
				//设置任务状态为: 推车拣选进行中
				task.setStatus("11"); //任务状态( 1.创建任务 2.已分配拣货任务  3.已拣货  4. 已分配灯光拣选任务  5.已经灯光拣选  6.已分配包装任务  7.已包装  8.已分配发货任务  9.已发货  10.灯光拣选进行中.. 11.推车拣选进行中..)
				task.setPickcarId(car.getId());
				task.setPickcarCode(car.getCarCode());
				task.setPickerId(user.getId());
				this.workTaskDao.save(task);
				
				return "success";
		
		} catch (Exception e) {
			throw new Exception(e);
	    }
		
	}
	
	/**
	 * 
	 * @param jobuuid
	 * @return
	 */
	@Transactional(readOnly=true)
	public User findUserByjobuuid(String jobuuid) {
		User user=userDao.findByJobuuid(jobuuid);
		return user;
	}

	/**
	 * 释放
	 * @param pickCarId
	 * @throws Exception 
	 */
	@Transactional(readOnly = false, rollbackFor=Exception.class)
	public void free(Long pickCarId) throws Exception {
		try {
			
			PickCar car=this.pickCarDao.findOne(pickCarId);
			car.setBatchCode(null);
			car.setTaskCode(null);
			car.setStatus("free");
			this.pickCarDao.save(car);
			
			List<PickCarStock> stockList=this.pickCarStockDao.loadStockByCarId(pickCarId);
			for (PickCarStock stock : stockList) {
				stock.setBatchCode(null);
				stock.setTaskCode(null);
				stock.setGoodsInfo(null);
				stock.setGoodsNum(0);
				stock.setStatus("free");
				stock.setOrderno(null);
			}
			this.pickCarStockDao.save(stockList);
			
			List<PickCarStockSku> stockSkuList=this.pickCarStockSkuDao.loadByCarId(pickCarId);
			this.pickCarStockSkuDao.delete(stockSkuList);
			
		} catch (Exception e) {
			throw e;
		}
		
	}

	/**
	 * 任务绑定推车
	 * @param carCode 车编码
	 * @param taskCode 任务编码
	 * @return busy：推车被占用  success:推车绑定任务成功
	 * @throws Exception 
	 */
	@Transactional(readOnly = false, rollbackFor=Exception.class)
	public String fastBindCar(String carCode, String taskCode,Long pickerId,String jobuuid) throws Exception {
		try {
				PickCar car=loadCarByCode(carCode);
				if(null == car){
					return "noexist";
				}
				User pickUser=userDao.findOne(pickerId);
				User assignUser=userDao.findByJobuuid(jobuuid);
				List<PickCarStock> stockList=null;
				List<PickCarStockSku> stockSkuList=null;
				WorkTask task=workTaskDao.loadTaskByTaskCode(taskCode);
				if(!"1".equals(task.getStatus())){
                    return "errorStatue";
                }
				String batchCode=task.getBatchCode();
				//拣选车被其它任务占用
				if(car.getStatus().equals("busy")){
					return "busy"; 
				}
				//continue任务
				if(task.getStatus().equals("11") ){
					if(!carCode.equals(task.getPickcarCode())){
						return "unfixed";  //推车编码和任务不匹配
					}else{
						return "continue"; //继续任务
					}
				}
				//车位不够
				if(car.getStockNum()<task.getOrderQty()){
					return "less"; 
				}	
				//订单信息
				Map<String, Object> param=new HashMap<String, Object>();
			    param.put("taskCode",taskCode);
			    param.put("cancelStatus","ok");
			    List<WorkOrder> orderList=workOrderService.loadOrder(param);
			    //绑定拣选车
				car.setStatus("busy");
				car.setBatchCode(batchCode);
				car.setTaskCode(taskCode);
				pickCarDao.save(car);
				stockList=new ArrayList<PickCarStock>();
				stockSkuList=new ArrayList<PickCarStockSku>();
				//绑定拣选车位、写入拣选车明细信息
				for (WorkOrder workOrder : orderList) {
					int rankno=workOrder.getRankno();
					PickCarStock stock=pickCarStockDao.loadStockByCondition(car.getId(),rankno+"");
					int goodsNum=0; String goodsInfo="";
		            List<EdiOrderItem> itemList=workOrder.getOrder().getOrderItems();
					for (EdiOrderItem orderItem : itemList) {
						int _qty=orderItem.getQty();
						String _sku=orderItem.getSku();
						goodsNum+=_qty;
		                goodsInfo+=_sku+"_"+_qty+";";
		                for(int i=0;i<_qty;i++){
		                	PickCarStockSku stockSku=new PickCarStockSku();
		                	stockSku.setCar(car);
		                	stockSku.setStock(stock);
		                	stockSku.setSku(_sku);
		                	stockSku.setNum(1);
		                	stockSku.setBatchCode(batchCode);
		                	stockSku.setTaskCode(taskCode);
		                	stockSku.setUpStatus("0");
		                	stockSkuList.add(stockSku);
		                }
					}
					
					stock.setStatus("busy");
					stock.setGoodsInfo(goodsInfo);
					stock.setGoodsNum(goodsNum);
					stock.setBatchCode(batchCode);
					stock.setTaskCode(taskCode);
					stock.setOrderno(workOrder.getOrder().getOrdeno());
					stockList.add(stock);
				}
				pickCarStockDao.save(stockList);
				pickCarStockSkuDao.save(stockSkuList);
				
				//设置任务状态为: 推车拣选进行中
				task.setStatus("11"); //任务状态( 1.创建任务 2.已分配拣货任务  3.已拣货  4. 已分配灯光拣选任务  5.已经灯光拣选  6.已分配包装任务  7.已包装  8.已分配发货任务  9.已发货  10.灯光拣选进行中.. 11.推车拣选进行中..)
				task.setPickcarId(car.getId());
				task.setPickcarCode(car.getCarCode());
				task.setPickerId(pickUser.getId());
				task.setAssignerId(assignUser.getId());
				task.setFastFlag(1);
				this.workTaskDao.save(task);
				saveWorkLog(assignUser, task,"11","快捷领取推车拣选进行中..("+task.getTaskCode()+")");
				return "success";
		} catch (Exception e) {
			throw new Exception(e);
	    }
		
	}
/**
 * 保存工作日志
 * @param taskCode
 * @param assignUser
 * @param task
 */
	@Transactional(readOnly = false, rollbackFor=Exception.class)
	public void saveWorkLog(User assignUser, WorkTask task,String status,String msg) {
		WorkLog workLog=new WorkLog(
		    		task.getBatchCode(),
		    		status, //任务状态( 1.创建任务 2.已分配拣货任务  3.已拣货  4. 已分配灯光拣选任务  5.已经灯光拣选  6.已分配包装任务  7.已包装  8.已分配发货任务  9.已发货  10.灯光拣选进行中.. 11.推车拣选进行中..)
		    		msg,
		    		new Date(),
		    		assignUser);
		workLogDao.save(workLog);
	}
	
	
	/**
	 * 商品上架NEW
	 * @param carId 拣选车ID
	 * @param taskId 任务ID
	 * @param stockId 拣货车位ID
	 * @throws Exception 
	 */
	@Transactional(readOnly = false, rollbackFor = Exception.class)
	public String setGoodsNew(Long carId, Long taskId,
			String stockId,String sku,Integer limitNum) throws Exception {

		WorkTask task = this.workTaskDao.findOne(taskId);
		PickCar car = this.pickCarDao.findOne(carId);

		String taskCode = task.getTaskCode();

		if (car.getTaskCode() == null) {
			log.error("car"+car.getCarCode()+"没有绑定任务");
			return "error";
		}
		
	    if (car.getTaskCode().equals(taskCode)) {
			// 修改拣选车位明细的状态
			updateCarStockSkuStatus(stockId,sku,limitNum);
			List<PickCarStockSku> unSetList = this.pickCarStockSkuDao.loadUnSet(task.getPickcarId(), taskCode);
			if (unSetList != null && unSetList.size() == 0) {
				if ("car".equals(task.getPickModel())) {
					//清空拣货车资料
					clearPickCar(carId + "");
					// 清空拣货车位
					clearPickCarStock(car.getCarCode());
					// 清除拣选车位明细
					clearPickCarStockSku(carId + "");
				}

			}
			return "success";
		} else {
			log.error("car"+car.getCarCode()+"绑定其他任务"+car.getTaskCode());
			return "error";
		}

	}
	/**
	 * 根据任务号和推车码 获取当前扫描的sku的数量和筐位,一次只取一条数据
	 * @param taskCode
	 * @param carCode
	 * @return
	 */
	public Map<String,Object> loadCarStock(String taskCode,String carCode,String sku){
		   String sql="select a.task_code,a.stock_code,a.car_code,b.sku,sum(num) as num,b.stock_id from pick_car_stock a,pick_car_stock_sku b "
		   		+ " where a.id=b.stock_id and a.car_code='"+ carCode +"' and a.task_code='"+ taskCode +"' and b.sku='"+ sku +"' and up_status='0' "
		   		+ " GROUP BY a.task_code,a.stock_code,a.car_code,b.sku,b.stock_id ORDER BY a.stock_code+0 limit 0,1";
		   //return jdbcTemplate.queryForMap(sql);
		   
		   List<Map<String,Object>> list = jdbcTemplate.queryForList(sql);
		   if (list == null || list.isEmpty()) {
			   return null;
		   }
		   return (Map<String, Object>) list.get(0);
	}
	
	/**
	 * 修改拣选车位明细的状态
	 * @param stockId
	 * @return
	 */
	public int updateCarStockSkuStatus(String stockId,String sku,Integer limitNum){
		   String sql="update pick_car_stock_sku set up_status='1' where stock_id='"+ stockId +"' and sku='"+ sku +"' and up_status<>'1' limit " +limitNum;
		   return jdbcTemplate.update(sql);
	}
	/**
	 * 释放推车，清空拣货车资料
	 * @param carId
	 * @return
	 */
	public int clearPickCar(String carId){
		   String sql="update pick_car set status='free',batch_code='',task_code='' where id='"+ carId +"'";
		   return jdbcTemplate.update(sql);
	}
	/**
	 * 清空拣货车位
	 * @param carCode
	 * @return
	 */
	public int clearPickCarStock(String carCode){
		   String sql="update pick_car_stock set goods_info='',goods_num=0,orderno='',batch_code='',task_code='',status='free' where car_code='"+ carCode +"'";
		   return jdbcTemplate.update(sql);
	}
	/**
	 * 清除拣选车位明细
	 * @param carId
	 * @return
	 */
	public int clearPickCarStockSku(String carId){
		   String sql="delete from pick_car_stock_sku where car_id='"+carId +"'";
		   return jdbcTemplate.update(sql);
	}

}